package com.runvp.common.pay.wechat;

import com.runvp.common.config.WechatConfigure;
import com.runvp.common.util.MoneyUtils;
import com.runvp.common.utils.uuid.IdUtils;
import com.wechat.pay.java.core.Config;
import com.wechat.pay.java.core.RSAConfig;
import com.wechat.pay.java.core.exception.ServiceException;
import com.wechat.pay.java.core.util.PemUtil;
import com.wechat.pay.java.service.payments.jsapi.JsapiService;
import com.wechat.pay.java.service.payments.jsapi.model.*;
import com.wechat.pay.java.service.payments.model.Transaction;
import lombok.extern.slf4j.Slf4j;

import java.math.BigDecimal;
import java.security.PrivateKey;
import java.util.LinkedHashMap;
import java.util.Map;

@Slf4j
public class JsapiClient {

    /**
     * 商户号
     */
    private String appId ;
    /**
     * 商户号
     */
    private String merchantId ;
    /**
     * 商户API私钥路径
     */
    private String privateKeyPath ;
    /**
     * 商户证书序列号
     */
    private String merchantSerialNumber ;
    /**
     * 微信支付平台证书路径
     */
    private String wechatPayCertificatePath ;
    /**
     * 微信支付 APIv3 密钥
     */
    private String apiV3Key ;

    private String notifyUrl ;

    private Config config ;
    private JsapiService service ;

    public void init(){
        this.appId = WechatConfigure.getApp_id();
        this.merchantId = WechatConfigure.getMch_id();
        this.privateKeyPath = WechatConfigure.getPrivateKeyPath();
        this.merchantSerialNumber = WechatConfigure.getMerchantSerialNumber();
        this.wechatPayCertificatePath = WechatConfigure.getWechatPayCertificatePath();
        this.apiV3Key = WechatConfigure.getKey();
        this.notifyUrl = WechatConfigure.getNotify_url();

        config =
                new RSAConfig.Builder()
                        .merchantId(merchantId)
                        .privateKeyFromPath(privateKeyPath)
                        .merchantSerialNumber(merchantSerialNumber)
                        .wechatPayCertificatesFromPath(wechatPayCertificatePath)
                        .build();

        service = new JsapiService.Builder().config(config).build();
    }

    public JsapiClient() {
        init();
    }

    /**
     * 下单
     * @param openId d
     * @param orderNo
     * @param money 支付金额
     * @return map
     */
    public Map<String, Object> pay(String openId, String orderNo, BigDecimal money) {
        PrepayRequest request = new PrepayRequest();
        Amount amount = new Amount();
        amount.setTotal(MoneyUtils.feeHandleTOInt(money));
        request.setAmount(amount);
        request.setAppid(appId);
        request.setMchid(merchantId);
        request.setDescription("商品信息");
        request.setNotifyUrl(notifyUrl);
        request.setOutTradeNo(orderNo);
        Payer payer = new Payer();
        payer.setOpenid(openId);
        request.setPayer(payer);
        PrepayResponse response = service.prepay(request);
        String packageStr = "prepay_id=" + response.getPrepayId();
        // 处理返回数据
        Map<String, Object> result = new LinkedHashMap<>();
        String timeStamp = String.valueOf(System.currentTimeMillis() / 1000);
        String nonceStr = IdUtils.fastSimpleUUID().toUpperCase();
        result.put("appId", appId);
        result.put("timeStamp", timeStamp);
        result.put("nonceStr", nonceStr);
        result.put("package", packageStr);
        PrivateKey privateKey = PemUtil.loadPrivateKeyFromPath(privateKeyPath);
        String sign = SignUtil.sign256(V3Sign.buildSignStr(result),privateKey);
        result.put("paySign", sign);
        result.put("signType", "RSA");
        return result;
    }

    /**
     * 查询支付状态
     */
    public Transaction queryOrderByOutOrderNo(String outOrderNo){
        QueryOrderByOutTradeNoRequest queryRequest = new QueryOrderByOutTradeNoRequest();
        queryRequest.setMchid(merchantId);
        queryRequest.setOutTradeNo(outOrderNo);
        try {
            Transaction result = service.queryOrderByOutTradeNo(queryRequest);
            return result;
        } catch (ServiceException e) {
            // API返回失败, 例如ORDER_NOT_EXISTS
            log.error("code=[%s], message=[{}]\n", e.getErrorCode(), e.getErrorMessage());
            log.error("reponse body=[{}]\n", e.getResponseBody());
            return null;
        }
    }
    /**
     * 关闭
     */
    public void close(String outTradeNo) {
        outTradeNo = "out_trade_no_001";
        CloseOrderRequest closeRequest = new CloseOrderRequest();
        closeRequest.setMchid(merchantId);
        closeRequest.setOutTradeNo(outTradeNo);
// 方法没有返回值，意味着成功时API返回204 No Content
        service.closeOrder(closeRequest);

    }

}